package com.company.zhishidian.fanshe;

import com.company.zhishidian.zhujie.Zhuji;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 反射 ***
 *  不建议在写应用中使用，因为编译器没法校验，很伤时间
 */
public class TestReflect {
    public static void main(String[] args) {
        try {
            // 封装该类的所有信息，属性，方法，构造方法
            // 类加载器加载
            Class clazz = Class.forName("com.company.zhishidian.zhujie.MyClass");
//            Class<MyClass> clazz = MyClass.class;
            // 获取类的注解
            // 第18行的那个加载器的话就可以不强制转换了，因为他支持泛型，传入字符串这个的不支持泛型
            Zhuji myAnno = (Zhuji) clazz.getAnnotation(Zhuji.class);
            System.out.println(myAnno.value());
            // 代表构造器对象,私有的也可以获取
            Constructor con = clazz.getDeclaredConstructor(int.class);
            Object obj = con.newInstance(20); // new MyClass(20);
            // 获取成员方法
            // 调用哪个方法，方法参数的类型
            Method method = clazz.getDeclaredMethod("method",String.class);
            // 获取方法的注解
            Zhuji myAnno2 = method.getAnnotation(Zhuji.class);
            System.out.println(myAnno2.value());
            // 返回一个result，传入一个world
            Object result = method.invoke(obj,"world");
            System.out.println(result);
            // 获取成员属性
            Field field = clazz.getDeclaredField("age");  // IllegalAccessException  非法访问私有成员
            // 获取属性的注解
            Zhuji myAnno3 = field.getAnnotation(Zhuji.class);
            System.out.println(myAnno3.value());
            // 解决办法 一：暴力获取，强行让其可以被访问
//            field.setAccessible(true);
//            // 传入属性值
//            field.set(obj,30);
//            // 输出属性
//            System.out.println(field.get(obj));
            // 解决办法 二       优雅的读取
            String setterMethodName = "set"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);
            System.out.println(setterMethodName);
            Method setterMethod = clazz.getMethod(setterMethodName,field.getType());
            setterMethod.invoke(obj,88);
            String getterMethodName = "get"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);
            Method getterMethod = clazz.getMethod(getterMethodName);
            Object getterResult = getterMethod.invoke(obj,null);
            System.out.println(getterResult);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
